/*
struct
go中的struct与C中的struct非常相似，并且go没有class
使用type <Name> struct{}定义结构，名称遵循可见性规则
支持指向自身的指针类型成员
支持匿名结构，可用作成员或定义成员变量
匿名机构也可以用于map的值
可以使用字面值对结构进行初始化
允许直接通过指针读写结构成员
相同类型的成员可进行直接拷贝赋值
支持==与!=比较运算符，但不支持>或<
支持匿名字段，本质上定义了某个类型名为名称的字段
嵌入结构作为匿名字段看起来像继承，但不是继承
可以使用匿名字段指针
*/
package main

import (
	"fmt"
)

type Person1 struct {
	Name string
	Age  int
}
type Person2 struct {
	Name    string
	Age     int
	Contact struct {
		Phone, City string
	}
}
type Person3 struct {
	string
	int
}
type Human struct {
	Sex int
	Age int
}

type Teacher struct {
	Human
	Name string
	Age  int
}
type Student struct {
	Human
	Name string
	Age  int
}

func main() {
	fmt.Println("---------------struct声明，初始化，作为函数参数--------------------")
	a := &Person1{
		Name: "jeo", //字面值初始化
		Age:  19,
	}
	//	a.Name = "ok"//go中（通过指针/变量）访问成员统一通过.
	ParameterCopyValue(*a)
	fmt.Println("main", *a)
	ParameterPointer(a)
	fmt.Println("main", *a)
	fmt.Println("---------------匿名struct--------------------")
	b := &struct {
		Name string
		Age  int
	}{
		Name: "jeo",
		Age:  19,
	}
	fmt.Println(b)
	fmt.Println("---------------匿名struct成员--------------------")
	c := &Person2{Name: "jeo", Age: 19}
	c.Contact.Phone = "12345678901"
	c.Contact.City = "beijing"
	fmt.Println(c)

	fmt.Println("---------------匿名字段--------------------")
	d := &Person3{"jeo", 19}
	fmt.Println(d)
	fmt.Println("---------------比较== !=--------------------")
	e1 := Person1{Name: "jeo", Age: 19}
	e2 := Person1{Name: "jeo", Age: 19}
	e3 := Person1{Name: "jeo", Age: 20}
	fmt.Println(e1 == e2)
	fmt.Println(e1 != e3)
	fmt.Println(&e1 != &e2) //不同的对象的地址不一样
	fmt.Println("---------------嵌入struct--------------------")
	f1 := Teacher{Name: "jeo", Age: 19, Human: Human{Sex: 0}}
	f2 := Student{Name: "jeo", Age: 20, Human: Human{Sex: 1}}
	fmt.Println(f1, f2)
	f1.Sex = 1
	fmt.Println(f1)
	f1.Age = 21
	f1.Human.Age = 100 //当有同名成员时，通过嵌入类型默认名称区别
	fmt.Println(f1)
}

func ParameterCopyValue(per Person1) {
	fmt.Println("in func ParameterCopyValue")
	per.Age = 13
	fmt.Println(per)
}

func ParameterPointer(per *Person1) {
	fmt.Println("in func ParameterPointer")
	per.Age = 13
	fmt.Println(per)
}
